package Command;

import java.util.ArrayList;

public class SqlStringChecker {

	public SqlStringChecker()
	{
		
	}
	
	public ArrayList<Command> splitCommand(String str)
	{ 
		String sql = " " + str;
		ArrayList<Command> commands = new ArrayList<Command>();
		ArrayList<Integer> commandIndices = new ArrayList<Integer>();
		
		String[] keys = Command.mainQuery;
		
		for(int i = 0 ; i < keys.length; i++)
			Command.countCommand(commandIndices, keys[i], sql.toLowerCase(), 0);
		
		sortIndices(commandIndices);		
		
		// Split command
		for(int i = 0 ; i < commandIndices.size(); i++)
		{
			String sub = "";
			if(i == commandIndices.size() - 1)
				sub = sql.substring(commandIndices.get(i));
			else
				sub = sql.substring(commandIndices.get(i) , commandIndices.get(i + 1));
			
			if(Command.isDelete(sub.toLowerCase()))
				commands.add(new Delete(sub));
			else if(Command.isSelect(sub.toLowerCase()))
				commands.add(new Select(sub));
			else if(Command.isInsert(sub.toLowerCase()))
				commands.add(new Insert(sub));
			else if(Command.isUpdate(sub.toLowerCase()))
				commands.add(new Update(sub));
		}
		
		ArrayList<Command> ret = new ArrayList<Command>();
		// Merge if exist 2 select in one case
		for(int i = 0 ; i < commands.size(); i++)
		{
			if(i == commands.size() - 1)
			{
				ret.add(commands.get(i));
				break;
			}
			
			if(commands.get(i) instanceof Select
					&& commands.get(i + 1) instanceof Select)
			{
				// First query have where
				if(isMergeInWhere(i, sql.toLowerCase(), commands) ||		
						isMergerInHaving(i, sql.toLowerCase(), commands))
				{
					// merge
					commands.get(i).mergeSql(commands.get(i+1).getSql().toLowerCase());
					ret.add(commands.get(i));
					i++;
				}
				else
				{
					// none merge
					ret.add(commands.get(i));
				}
			}
			else
			{
				ret.add(commands.get(i));
			}
		}
		
		return ret;
	}
	
	private boolean isMergerInHaving(int index, String fullSql, ArrayList<Command> commands)
	{
		boolean ret = false;
		Command first = commands.get(index);
		Command second = commands.get(index + 1);
		Command third = null;
		if(commands.size() > index + 2)
		{
			third = commands.get(index + 2);
		}
		
		if(Command.isHaveHaving(first.getSql()))
		{
			System.out.println("Have having");
			String firstSql = first.getSql();
			String secondSql = second.getSql();
			
			int conditionIndex = fullSql.indexOf(firstSql) + firstSql.indexOf("having") + "having".length() + 1;			
			int secondSqlIndex = fullSql.indexOf(secondSql, conditionIndex);					
			String condition = fullSql.substring(conditionIndex, secondSqlIndex + 1);
			
			ret = checkMerge(fullSql, ret, third, conditionIndex,
					secondSqlIndex, condition);
			
		}
		
		return ret;
	}
	
	private boolean isMergeInWhere(int index, String fullSql, ArrayList<Command> commands)
	{
		boolean ret = false;
		Command first = commands.get(index);
		Command second = commands.get(index + 1);
		Command third = null;
		if(commands.size() > index + 2)
		{
			third = commands.get(index + 2);
		}
		
		if(Command.isHaveWhere(first.getSql()))
		{
			System.out.println("Have where");
			String firstSql = first.getSql();
			String secondSql = second.getSql();
			
			int conditionIndex = fullSql.indexOf(firstSql) + firstSql.indexOf("where") + "where".length() + 1;			
			int secondSqlIndex = fullSql.indexOf(secondSql);	
			String condition = fullSql.substring(conditionIndex, secondSqlIndex + 1);
			
			ret = checkMerge(fullSql, ret, third, conditionIndex,
					secondSqlIndex, condition);
			
		}
		
		return ret;
	}

	private boolean checkMerge(String fullSql, boolean ret, Command third,
			int conditionIndex, int secondSqlIndex, String condition) {
		if(Command.isHaveExistsFunction(condition)
				&& !Command.isHaveOperator(condition))
		{
			// Second select in right hand of exist
			int indexRightHand = Command.rightHandOfExistFunction(condition);
			String rightHand = fullSql.substring(conditionIndex + indexRightHand , secondSqlIndex);				
			
			String secondRightHand = "";
			
			if(third == null)
			{
				secondRightHand = fullSql.substring(secondSqlIndex);
			}
			else
			{
				secondRightHand = fullSql.substring(secondSqlIndex, 
						fullSql.indexOf(third.getSql()));
			}
			
			boolean rightHandDontHave = !Command.isHaveSymbols(rightHand) && !Command.isHaveCharacters(rightHand) && !Command.isHaveNumber(rightHand);
			
			if( (rightHandDontHave && Command.startWithOpenParentheses(rightHand))
					&&  Command.endWithCloseParentheses(secondRightHand))
				ret = true;
			
		}
		else if (!Command.isHaveExistsFunction(condition)
				&& Command.isHaveOperator(condition))
		{
			// Second select in right hand of operator
			System.out.println("Second select in right hand of operator");
			
			int indexRightHand = Command.rightHandOfOperator(condition);
			
			String rightHand = fullSql.substring(conditionIndex + indexRightHand - 1, secondSqlIndex);			
		
String secondRightHand = "";
			
			if(third == null)
			{
				secondRightHand = fullSql.substring(secondSqlIndex);
			}
			else
			{
				secondRightHand = fullSql.substring(secondSqlIndex, 
						fullSql.indexOf(third.getSql()));
			}
			
			boolean rightHandDontHave = !Command.isHaveSymbols(rightHand) && !Command.isHaveCharacters(rightHand) && !Command.isHaveNumber(rightHand);
			
			if( rightHandDontHave || 
				((Command.startWithAll(rightHand) || Command.startWithAny(rightHand) || Command.startWithOpenParentheses(rightHand)) && Command.endWithCloseParentheses(secondRightHand)) )
				ret = true;
		}
		else if (!Command.isHaveExistsFunction(condition)
				&& !Command.isHaveOperator(condition))
		{
			// Second select in left hand of operator
			System.out.println("Second select in left hand of operator");
			
			int indexRightHand = Command.rightHandOfOperator(condition);
			
			String rightHand = fullSql.substring(conditionIndex + indexRightHand , secondSqlIndex);			
		
			String secondRightHand = "";
			
			if(third == null)
			{
				secondRightHand = fullSql.substring(secondSqlIndex);
			}
			else
			{
				secondRightHand = fullSql.substring(secondSqlIndex, 
						fullSql.indexOf(third.getSql()));
			}
			
			int secondRightHandIndex = fullSql.indexOf(secondRightHand);
			int thirdRightHandIndex = secondRightHandIndex + secondRightHand.indexOf(")") + 1;
			String thirdRightHand = fullSql.substring(thirdRightHandIndex);
			secondRightHand = fullSql.substring(secondRightHandIndex, thirdRightHandIndex);
			
			if(  Command.startWithOperator(thirdRightHand) &&
					Command.startWithOpenParentheses(rightHand) && 
					Command.endWithCloseParentheses(secondRightHand)) 
				ret = true;
		}
		return ret;
	}
	
	private void sortIndices(ArrayList<Integer> commandIndices)
	{
		for(int i = 0 ; i < commandIndices.size() - 1; i++)
		{
			for(int j = i + 1; j < commandIndices.size(); j++)
			{
				if(commandIndices.get(j) < commandIndices.get(i))
				{
					int temp = commandIndices.get(j);
					commandIndices.set(j, commandIndices.get(i));
					commandIndices.set(i, temp);
				}
			}
		}
	}	
	
}
